package com.pku.ss.ui;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
//import org.eclipse.swt.widgets.TreeItem;

import com.ss.cg.CallGraph;
import com.ss.cg.CallGraphNode;
import com.ss.cg.CallGraphTest;
import com.ss.cg.CallSite;
import com.ss.cg.IPrintCG;
import com.ss.cg.PrintCGDot;


class CGExplorer extends Composite {
	private String filePath;

	private Text addressControl;
	private Tree methodTreeControl;
	private Tree fileTreeControl;
	
	private Canvas imageCanvas;
	private Image cfgImage ;
	private GridData imageGridData;
	private String imagePath;

	private SashForm astSashFormVertical;
	private SashForm astSashFormHorizontal2;

	// private static DefaultMutableTreeNode root;
	public String fileName = "";

	private List<File> fsl = new LinkedList<File>();

	static String JAVASUFFIX = ".java";

	public String getFilePath() {
		return filePath;
	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

	public CGExplorer(Composite parent, int style) {
		super(parent, style);

		GridLayout gridLayout = new GridLayout();
		super.setLayout(gridLayout);
		Composite composite = new Composite(this, SWT.NONE);
		gridLayout = new GridLayout();
		gridLayout.numColumns = 3;
		composite.setLayout(gridLayout);
		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Button button = new Button(composite, SWT.PUSH);
		button.setText("File...");
		button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));

		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				Shell shell = ((Button) event.widget).getShell();
				FileDialog dialog = new FileDialog(shell, SWT.PRIMARY_MODAL
						| SWT.OPEN);
				dialog.setText("Java Source File");
				dialog.setFilterExtensions(new String[] { "*.java" });
				String file = dialog.open();

				if (file == null)
					return;
				addressControl.setText(file);
				go(file);
			}
		});

		this.addressControl = new Text(composite, SWT.BORDER);
		this.addressControl
				.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		button = new Button(composite, SWT.PUSH);
		button.setText("Go");
		button.getShell().setDefaultButton(button);
		button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				go(addressControl.getText());
			}
		});

		this.astSashFormVertical = new SashForm(this, SWT.VERTICAL);
		this.astSashFormVertical.setLayoutData(new GridData(
				GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
						| GridData.HORIZONTAL_ALIGN_FILL
						| GridData.VERTICAL_ALIGN_FILL));

		this.astSashFormHorizontal2 = new SashForm(this.astSashFormVertical,
				SWT.HORIZONTAL);
		this.astSashFormHorizontal2.setLayoutData(new GridData(
				GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
						| GridData.HORIZONTAL_ALIGN_FILL
						| GridData.VERTICAL_ALIGN_FILL));

		this.fileTreeControl = new Tree(this.astSashFormHorizontal2, SWT.BORDER
				| SWT.SINGLE);
		this.fileTreeControl.setLayoutData(new GridData(GridData.GRAB_VERTICAL
				| GridData.VERTICAL_ALIGN_FILL));

		this.fileTreeControl.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {

				TreeItem[] item = fileTreeControl.getSelection();
				String file = item[0].getText();
				System.out.println(file);
				if (file.endsWith(".java")) {
					addressControl.setText(file);
					System.out.println(file);
					go(file);
				}

			}

		});

		SashForm sashFormHorizontal = new SashForm(this.astSashFormVertical,
				SWT.HORIZONTAL);
		this.imageGridData = new GridData(GridData.GRAB_HORIZONTAL
				| GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL
				| GridData.VERTICAL_ALIGN_FILL);
		sashFormHorizontal.setLayoutData(imageGridData);

		this.methodTreeControl = new Tree(sashFormHorizontal, SWT.BORDER | SWT.SINGLE);
		this.methodTreeControl.setLayoutData(new GridData(GridData.GRAB_VERTICAL
				| GridData.VERTICAL_ALIGN_FILL));
		this.methodTreeControl.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				TreeItem[] item = methodTreeControl.getSelection();
				String methodName = item[0].getText();
				File imageFile = new File(System.getProperty("user.dir") +"\\DOT\\"+methodName+"_CG.jpg");
				if(imageFile.exists()){
					cfgImage = new Image(e.display,System.getProperty("user.dir") +"\\DOT\\"+methodName+"_CG.jpg");
//					Image image = new Image(e.display,getClass(),getResourceAsStream("Idea.jpg"));
//					Point imagePoint = imageCanvas.getSize();
//					ImageData newImageData = new ImageData("D:\\DOT\\"+methodName+"_CFG.jpg").scaledTo(imagePoint.x, imagePoint.y);
//					ImageLoader imageLoader = new ImageLoader();
//					imageLoader.data = new ImageData[] {newImageData};
//					imageLoader.save("D:\\NEWDOT\\"+methodName+"_CFG.jpg",SWT.IMAGE_JPEG);
//					newCfgImage = new Image(Display.getDefault(),"D:\\NEWDOT\\"+methodName+"_CFG.jpg");
					imageCanvas.redraw();
					imagePath = System.getProperty("user.dir") +"\\DOT\\"+methodName+"_CG.jpg";
				}
			}
		});
		
		/*this.textControl = new StyledText(sashFormHorizontal, SWT.BORDER
				| SWT.READ_ONLY | SWT.H_SCROLL | SWT.V_SCROLL);
		this.textControl.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL
				| GridData.VERTICAL_ALIGN_FILL));*/
//		this.imageComposite = new Composite(sashFormHorizontal,SWT.NONE);
//		ScrollComponent scrollComposite = new ScrollComponent(sashFormHorizontal,SWT.NONE);
		this.imageCanvas = new Canvas(sashFormHorizontal,SWT.RESIZE);
//		this.imageCanvas = new Canvas(sashFormHorizontal,SWT.RESIZE);
		imageCanvas.addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent e) {
                if(cfgImage!=null){
                	int width = cfgImage.getBounds().width;
                	int height = cfgImage.getBounds().height;
                	int canvasWidth = imageCanvas.getBounds().width;
                	int canvasHeight = imageCanvas.getBounds().height;
                	/*System.out.println("width:"+width);
                	System.out.println("height:"+height);
                	System.out.println("imageCanvas.getBounds().width:"+ canvasWidth);
                	System.out.println("imageCanvas.getBounds().height:"+ canvasHeight);*/
                	e.gc.setAdvanced(true);
                	e.gc.setAntialias(SWT.ON);
                	e.gc.drawImage(cfgImage,0,0,width,height,0,0,canvasWidth,canvasHeight);
                	e.gc.dispose();
                	/*ImageData data=cfgImage.getImageData();
            	    ImageData data1=data.scaledTo(imageCanvas.getSize().x, imageCanvas.getSize().y);
            	    Image im=new Image(e.display,data1);
                	e.gc.setAdvanced(true);
                	e.gc.setAntialias(SWT.ON);
            	    e.gc.drawImage(im, 0, 0);*/
                }
                    
            }
        });
		imageCanvas.addMouseListener(new MouseListener() {
			@Override
			public void mouseUp(MouseEvent arg0) {	
				 
			}
			@Override
			public void mouseDown(MouseEvent arg0) {

			}
			
			@Override
			public void mouseDoubleClick(MouseEvent arg0) {
				try {
					java.lang.Runtime.getRuntime().exec(
							"rundll32.exe C:\\WINDOWS\\system32\\shimgvw.dll,ImageView_Fullscreen "+ imagePath)
							.waitFor();
				} catch (IOException e1) {
					e1.printStackTrace();
				} catch (InterruptedException e2) {
					e2.printStackTrace();
				}
				
			}
		});
		imageCanvas.scroll(0, 0, 0, 0, this.imageCanvas.getSize().x, this.imageCanvas.getSize().y, true);

		this.astSashFormVertical.setWeights(new int[] { 80, 80});
	}
	
	/***
	 * 
	 */
	void initFileTreeControl() {
		TreeItem item = new TreeItem(fileTreeControl, SWT.None);
		item.setText("files");
//		System.out.println("******" + this.filePath);
		File file = new File(fileName);
		if (file.isDirectory()) {
			this.check(file, item);
		} else if (file.isFile()) {
			this.fsl.add(file);
		}
	}


	private void go(String filePath) {
		try {
			SetFile(filePath);
			// SetFilePath(addressControl.getText());
		} catch (InterruptedException e) {
			reset();
		} catch (InvocationTargetException e) {
			reset();
			// showError(e.getTargetException());
		} catch (Exception e) {
			reset();
			// showError(e);
		}
	}

	private void check(File path, TreeItem item) {
		File[] ffs = path.listFiles();
		for (int i = 0; i < ffs.length; i++) {
			if (ffs[i].isDirectory()) {
				TreeItem subItem = new TreeItem(item, SWT.None);
				subItem.setText(ffs[i].toString());
				check(ffs[i], subItem);
			} else if (ffs[i].getName().endsWith(".java")) {
				TreeItem subItem = new TreeItem(item, SWT.None);
				subItem.setText(ffs[i].toString());
				fsl.add(ffs[i]);

			}
		}
	}

	private void reset() {
		// this.fileTreeControl.removeAll();
		this.methodTreeControl.removeAll();
//		this.textControl.setText("");
	}

	private void SetFile(final String path) throws InterruptedException,
			InvocationTargetException {
		reset();
		ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
		dialog.run(true, true, new IRunnableWithProgress() {
			public void run(final IProgressMonitor monitor)
					throws InvocationTargetException {
				try {
					if (monitor.isCanceled())
						return;
					getDisplay().syncExec(new Runnable() {
						
						public void run() {
					IPrintCG printCg=new PrintCGDot("DOT\\");
					CallGraphTest c=new CallGraphTest(fileName);
					
					//get CallGraph
					List<CallGraph> cgs=c.getCallGraph();
					// print CallGraph
					String fileName1="";
					File f=new File(path);
					if(f.isFile()){
						fileName1=f.getName().replace(".java", "");
					}
					TreeItem collerTtem=null;
					CallGraphNode node=null;
					for(CallGraph cg:cgs){
						printCg.visit(cg);
						for(CallSite site:cg.getEges()){
							
							if(node==null||!node.getIdentifier().equals(site.getCaller().getIdentifier()))
							{
								node=cg.Search(site.getCaller().getIdentifier()) ;
								if(!fileName1.equals(node.getBelongClass()))
								{
									continue;
								}
								if(!node.getIsVisited()){
									node.setIsVisited(true);
								}
								else{
									continue;
								}
							}
							else
							{
								continue;
							}
							collerTtem = new TreeItem(methodTreeControl, SWT.None);
							collerTtem.setText(node.getIdentifier());
							for(CallGraphNode callee:cg.getAllCallees(node)){
								 TreeItem calleeTtem = new TreeItem(collerTtem, SWT.None);
								 calleeTtem.setText(callee.getIdentifier());
							}
						}
					}
						}
					});
				}
				catch (Exception e) {
					e.printStackTrace();
					throw new InvocationTargetException(e);
				}
			}
		});
	}

}
